using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;

/// <summary>
/// Buff 基类
/// </summary>
public abstract class BuffBase : IDisposable
{
    /// <summary>
    /// Buff 数据
    /// </summary>
    public BuffData BuffData { get; private set; }

    /// <summary>
    /// 技能ID  
    /// 0 表示非技能来源
    /// </summary>
    public uint SkillId { get; }

    /// <summary>
    /// 施法者
    /// </summary>
    public Entity Caster { get; private set; }

    /// <summary>
    /// 作用对象
    /// </summary>
    public Entity Target { get; private set; }

    /// <summary>
    /// 最大层数
    /// </summary>
    public int MaxStack { get; private set; }

    /// <summary>
    /// 当前层数
    /// </summary>
    public int CurrentStack { get; private set; }

    /// <summary>
    /// 当前剩余时间
    /// </summary>
    public float Duration { get; private set; }

    /// <summary>
    /// 取消令牌
    /// </summary>
    private CancellationTokenSource m_Cts;

    /// <summary>
    /// 创建Buff  实例构造函数
    /// </summary>
    /// <param name="buffData"></param>
    /// <param name="caster">施法者</param>
    /// <param name="target">作用对象</param>
    /// <param name="skillId">技能ID</param>
    protected BuffBase(BuffData buffData, Entity caster, Entity target, uint skillId = 0)
    {
        BuffData = buffData;
        Caster = caster;
        Target = target;
        Duration = BuffData.Duration;
        SkillId = skillId;
    }

    /// <summary>
    /// 执行Buff
    /// </summary>
    /// <returns></returns>
    public async UniTask RunAsync()
    {
        Logger.Log("BuffBase", $"RunAsync 开始执行，buffName={BuffData?.BuffName}, target={Target?.name}, duration={Duration}秒, delay={BuffData?.Delay}秒");
        m_Cts = new CancellationTokenSource();
        var token = m_Cts.Token;

        try
        {
            if (BuffData.Delay > 0)
            {
                Logger.Log("BuffBase", $"等待延迟时间: {BuffData.Delay}秒, buffName={BuffData.BuffName}, target={Target.name}");
                await UniTask.Delay(TimeSpan.FromSeconds(BuffData.Delay), cancellationToken: token);
            }

            Logger.Log("BuffBase", $"调用 OnStart, buffName={BuffData.BuffName}, target={Target.name}");
            OnStart();

            float elapsed = 0f;
            while (elapsed < Duration && !token.IsCancellationRequested)
            {
                await UniTask.Yield(PlayerLoopTiming.Update, token);
                float dt = Time.deltaTime;
                elapsed += dt;
                OnTick(elapsed);
            }

            if (!token.IsCancellationRequested)
            {
                Logger.Log("BuffBase", $"调用 OnFinish, buffName={BuffData.BuffName}, target={Target.name}");
                OnFinish();
            }
        }
        catch (OperationCanceledException e)//操作取消
        {
            Logger.Log("BuffBase", $"Buff被取消，buffName={BuffData?.BuffName}, target={Target?.name}");
            throw e;
        }
        finally
        {
            Logger.Log("BuffBase", $"调用 OnRemove, buffName={BuffData?.BuffName}, target={Target?.name}");
            OnRemove();
        }
        
        Logger.Log("BuffBase", $"RunAsync 执行完成，buffName={BuffData?.BuffName}, target={Target?.name}");
    }

    /// <summary>
    /// 刷新持续时间（重置计时器）
    /// </summary>
    /// <param name="newDuration"></param>
    public void Refresh(float newDuration)
    {
        Duration = newDuration;
    }

    /// <summary>
    /// 添加层数，默认不可超过MaxStack
    /// </summary>
    /// <returns></returns>
    public bool AddStack()
    {
        if (CurrentStack >= MaxStack) return false;
        CurrentStack++;
        OnStackAdded();
        return true;
    }

    /// <summary>
    /// 外部强制移除
    /// </summary>
    public void Cancel()
    {
        if (m_Cts != null)
        {
            m_Cts.Cancel();
        }
    }

    /// <summary>
    /// 释放内存
    /// </summary>
    public void Dispose()
    {
        if (m_Cts != null)
        {
            m_Cts.Dispose();
            m_Cts = null;
        }
    }

    #region 虚方法
    protected virtual void OnStart() { }
    protected virtual void OnTick(float dt) { }
    
    /// <summary>
    /// 外部调用的Tick方法
    /// </summary>
    public virtual void Tick()
    {
        if (Duration > 0)
        {
            float dt = Time.deltaTime;
            Duration -= dt;
            OnTick(dt);
        }
    }

    protected virtual void OnFinish() { }

    protected virtual void OnRemove() { }

    protected virtual void OnStackAdded() { }

    public virtual bool IsCanMerge() { return false; }

    /// <summary>
    /// 检查Buff是否已完成
    /// </summary>
    /// <returns></returns>
    public virtual bool IsFinished()
    {
        return Duration <= 0 || Target == null || Target.HealthComponent.IsDead;
    }

    /// <summary>
    /// 获取剩余时间
    /// </summary>
    /// <returns></returns>
    public float GetRemainingTime()
    {
        return Duration;
    }

    /// <summary>
    /// 获取Buff强度（用于UI显示）
    /// </summary>
    /// <returns></returns>
    public virtual float GetBuffIntensity()
    {
        return 1.0f;
    }
    #endregion
}